package com.tr.syscms.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tr.common.util.CustomException;
import com.tr.common.util.JwtUtils;
import com.tr.common.util.Result;
import com.tr.common.util.ResultStatus;
import com.tr.common.vo.TreeNode;
import com.tr.syscms.entity.Menu;
import com.tr.syscms.mapper.MenuMapper;
import com.tr.syscms.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author xiijava
 * @since 2022-06-07
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MenuMapper menuMapper;

    @Override
    public Result queryButtonPermsByUserId(String token) {
        System.out.println(token);
        String id = JwtUtils.getMessageIdByJwtToken(token).get("id");
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        System.out.println(redisTemplate.hasKey(token));
        if(!redisTemplate.hasKey(token)){
            return new Result(500,"验证失败！",null);
        }
        //根据用户id查询对应按钮集合
        List<String> buttonList = menuMapper.queryButtonPermsByUserId(Integer.parseInt(id));
        return new Result(200,"成功！",buttonList);
    }

    @Override
    public Result queryTreeDataByUserId(String userId) {
        List<TreeNode> treeNodes = menuMapper.queryTreeDataByUserId(userId);
        //定义一个返回的结果集
        List<TreeNode> tempTreeNodes = new ArrayList<>();
        //拼装为树形数据
        if(treeNodes!=null&&treeNodes.size()>0){
            //循环遍历
            for (TreeNode treeNode : treeNodes) {
                //查找一级节点
                if(treeNode.getParentId()==0){
                    tempTreeNodes.add(treeNode);
                    //为一级的所有子节点查找并绑定孩子
                    findAndBindChild(treeNode,treeNodes);
                }
            }
        }
        return new Result(200,"成功!",tempTreeNodes);
    }

    /**
     * 查询所有菜单
     * @return
     */
    @Override
    public Result menuTreeData() {
        //查询所有数据
        List<TreeNode> treeNodes = menuMapper.queryAllTreeData();
        //定义一个返回的结果集
        List<TreeNode> tempTreeNodes = new ArrayList<>();
        //拼装为树形数据
        if(treeNodes!=null&&treeNodes.size()>0){
            //循环遍历
            for (TreeNode treeNode : treeNodes) {
                //查找一级节点
                if(treeNode.getParentId()==0){
                    tempTreeNodes.add(treeNode);
                    //为一级的所有子节点查找并绑定孩子
                    findAndBindChild(treeNode,treeNodes);
                }
            }
        }
        return new Result(200,"查询成功！",tempTreeNodes);
    }

    /**
     * 为所有子节点查找并绑定孩子
     * @param currentTreeNode 一级节点
     * @param treeNodeList 所有节点
     */
    private void findAndBindChild(TreeNode currentTreeNode, List<TreeNode> treeNodeList) {
        //再次循环查出的所有menu集合
        for (TreeNode treeNode : treeNodeList) {
            //判断循环节点的父节点id是否和当前节点的id相等，如果相等，说明当前循环节点是当前节点的孩子
            if (currentTreeNode.getId() == treeNode.getParentId()) {
                //是孩子，就要添加到当前节点的孩子集合
                //1，获取当前节点的孩子集合
                List<TreeNode> children = currentTreeNode.getChildren();
                //2,一定要判断孩子集合是否为空，如果是第一个孩子，孩子集合肯定为空，如果使用肯定空指针
                if (children == null) {
                    //3，如果为空，一定要实例化
                    children = new ArrayList<>();
                }
                // 4,根据上面判断，循环节点的父ID等于当前节点ID说明是孩子，加入
                children.add(treeNode);
                // 5,重新设置孩子集合
                currentTreeNode.setChildren(children);
                // 为了提高效率，每找到一个孩子，就从集合中删除，再次查找集合会变小，效率会变高 理论上可行，但是ArrayList不允许一边遍历一边删除元素
                // treeNodeList.remove(treeNode);
                //6,递归自己调用自己，再次判断当前循环有没有孩子，如果有执行相同操作
                findAndBindChild(treeNode, treeNodeList);
            }
        }
    }

    /**
     * 通过Map作为筛选条件分页查询
     *
     * @param map
     * @return
     */
    @Override
    public PageInfo queryAll(Map map) {
        if (map.get("pageNo") == null || map.get("pageSize") == null) {
            throw new CustomException(ResultStatus.NOT_ALLOWED_ACCESS.getReturncode(),
                    ResultStatus.NOT_ALLOWED_ACCESS.getReturnMessage());
        }
        Integer pageNo = Integer.valueOf(map.get("pageNo") + "");
        Integer pageSize = Integer.valueOf(map.get("pageSize") + "");
        //设值页码和每页显示数量
        PageHelper.startPage(pageNo, pageSize);
        //使用查询结果，构造PageInfo
        PageInfo pageInfo = new PageInfo(this.menuMapper.queryAll(map));
        return pageInfo;
    }



    @Override
    @Transactional
    public int addRoleAndMenu(int roleId,String menuIds) {
        //根据角色id删除该角色原来关联的所有权限
        int sucNum1 = menuMapper.deleteRoleMenuByRoleId(roleId);
        int sucNum2 = 0;
        //添加新的关联
        if(!StrUtil.isEmpty(menuIds)){
            String[] menuIdArray = menuIds.split(",");
            //定义入参List
            List<Map> mapList = new ArrayList<>();
            Map  map = null;
            //循环拼装参数
            for (String menuId : menuIdArray) {
                map = new HashMap();
                map.put("roleId",roleId);
                map.put("menuId",menuId);
                mapList.add(map);
            }
            //执行添加
            sucNum2 = menuMapper.addRoleAndMenu(mapList);
        }
        if(sucNum1>0&&sucNum2>0){
            return 1;
        }
        return 0;
    }

    @Override
    public List<Integer> queryMenuIdsByRoleId(int roleId) {
        return menuMapper.queryMenuIdsByRoleId(roleId);
    }

    @Override
    public List<TreeNode> queryAllTreeData() {
        //查询所有数据
        List<TreeNode> treeNodes = menuMapper.queryAllTreeData();
        //定义一个返回的结果集
        List<TreeNode> tempTreeNodes = new ArrayList<>();
        //拼装为树形数据
        if(treeNodes!=null&&treeNodes.size()>0){
            //循环遍历
            for (TreeNode treeNode : treeNodes) {
                //查找一级节点
                if(treeNode.getParentId()==0){
                    tempTreeNodes.add(treeNode);
                    //为一级的所有子节点查找并绑定孩子
                    findAndBindChild(treeNode,treeNodes);
                }
            }
        }
        return tempTreeNodes;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param menuId 主键
     * @return 实例对象
     */
    @Override
    public Menu queryById(Integer menuId) {
        return this.menuMapper.queryById(menuId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Menu> queryAllByLimit(int offset, int limit) {
        return this.menuMapper.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param menu 实例对象
     * @return 实例对象
     */
    @Override
    public Menu insert(Menu menu) {
        DateTime date = DateUtil.date();
        menu.setMenuName(menu.getLabel());
        menu.setCreateTime(date);
        menu.setUpdateTime(date);
        this.menuMapper.insert(menu);
        return menu;
    }

    /**
     * 修改数据
     *
     * @param menu 实例对象
     * @return 实例对象
     */
    @Override
    public Menu update(Menu menu) {
        this.menuMapper.updateMenu(menu);
        return this.queryById(menu.getMenuId());
    }

    /**
     * 通过主键删除数据
     *
     * @param menuId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer menuId) {
        return this.menuMapper.deleteById(menuId) > 0;
    }

}
